package com.example.demo.common;

import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * 统一路径的文件存储工具类
 */
public class FileStorageUtils {

    // 默认配置
    private static final String DEFAULT_BASE_DIR = "documents";
    private static final List<String> DEFAULT_DOCUMENT_TYPES = Arrays.asList(
            "text/plain",
            "application/msword",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "application/pdf",
            "image/jpeg",
            "image/png"
    );
    private static final DateTimeFormatter DEFAULT_DATE_FORMATTER =
            DateTimeFormatter.ofPattern("yyyyMMdd");

    private final Path basePath;
    private final DateTimeFormatter dateFormatter;
    private final List<String> allowedContentTypes;

    // ========== 构造方法 ==========

    /**
     * 默认构造（强制使用统一的documents目录结构）
     */
    public FileStorageUtils() {
        this(Paths.get(DEFAULT_BASE_DIR));
    }

    /**
     * 自定义基础路径构造
     */
    public FileStorageUtils(Path basePath) {
        this(basePath, DEFAULT_DATE_FORMATTER, DEFAULT_DOCUMENT_TYPES);
    }

    /**
     * 完全自定义构造
     */
    public FileStorageUtils(Path basePath, DateTimeFormatter dateFormatter,
                            List<String> allowedContentTypes) {
        // 强制规范化路径，确保一致性
        this.basePath = Objects.requireNonNull(basePath).toAbsolutePath().normalize();
        this.dateFormatter = Objects.requireNonNull(dateFormatter);
        this.allowedContentTypes = Objects.requireNonNull(allowedContentTypes);

        // 确保基础目录存在
        try {
            Files.createDirectories(this.basePath);
        } catch (IOException e) {
            throw new IllegalStateException("无法创建存储目录: " + basePath, e);
        }
    }

    // ========== 文件操作方法 ==========

    /**
     * 上传文件（强制使用统一路径结构）
     */
    public FileUploadResponse uploadFile(MultipartFile file) throws IOException {
        return uploadFile(null, file); // 不使用子目录
    }

    /**
     * 上传文件到指定子目录（可选）
     */
    public FileUploadResponse uploadFile(String subFolder, MultipartFile file) throws IOException {
        Objects.requireNonNull(file, "上传文件不能为null");

        // 构建存储路径（统一处理）
        Path uploadPath = buildStoragePath(subFolder);

        // 文件校验
        if (file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        String contentType = file.getContentType();
        if (contentType == null || !allowedContentTypes.contains(contentType)) {
            throw new IllegalArgumentException("不支持的文件类型: " + contentType);
        }

        // 生成安全文件名
        String originalFilename = sanitizeFilename(Objects.requireNonNull(file.getOriginalFilename()));
        String filename = generateSafeFilename(getFileExtension(originalFilename));

        // 保存文件
        Path targetLocation = uploadPath.resolve(filename);
        file.transferTo(targetLocation);

        // 返回统一格式的响应
        return new FileUploadResponse(
                subFolder != null ? subFolder : "",
                filename,
                originalFilename,
                contentType,
                file.getSize(),
                getRelativePath(subFolder, filename)
        );
    }

    /**
     * 加载文件（统一路径处理）
     */
    public Resource loadFileAsResource(String filename) throws IOException {
        return loadFileAsResource(null, filename); // 不使用子目录
    }

    /**
     * 从指定子目录加载文件（可选）
     */
    public Resource loadFileAsResource(String subFolder, String filename) throws IOException {
        Path filePath = buildStoragePath(subFolder).resolve(sanitizeFilename(filename)).normalize();

        // 安全检查
        if (!filePath.startsWith(basePath)) {
            throw new SecurityException("非法文件访问: " + filePath);
        }

        if (!Files.exists(filePath)) {
            throw new IOException("文件不存在: " + filePath);
        }

        return new UrlResource(filePath.toUri());
    }

    /**
     * 删除文件（统一路径处理）
     */
    public boolean deleteFile(String filename) throws IOException {
        return deleteFile(null, filename); // 不使用子目录
    }

    /**
     * 从指定子目录删除文件（可选）
     */
    public boolean deleteFile(String subFolder, String filename) throws IOException {
        Path filePath = buildStoragePath(subFolder).resolve(sanitizeFilename(filename)).normalize();

        // 安全检查
        if (!filePath.startsWith(basePath)) {
            throw new SecurityException("非法文件删除: " + filePath);
        }

        return Files.deleteIfExists(filePath);
    }

    // ========== 私有工具方法 ==========

    /**
     * 构建统一的存储路径
     */
    private Path buildStoragePath(String subFolder) throws IOException {
        Path path = basePath;
        if (subFolder != null && !subFolder.isEmpty()) {
            path = path.resolve(sanitizeFolderName(subFolder));
        }
        Files.createDirectories(path); // 确保目录存在
        return path;
    }

    /**
     * 获取相对路径（用于返回给客户端）
     */
    private String getRelativePath(String subFolder, String filename) {
        return (subFolder != null && !subFolder.isEmpty() ? subFolder + "/" : "") + filename;
    }

    private String sanitizeFolderName(String folder) {
        return folder.replaceAll("[^a-zA-Z0-9-_]", "_");
    }

    private String sanitizeFilename(String filename) {
        return filename.replaceAll("[^a-zA-Z0-9.\\-]", "_");
    }

    private String generateSafeFilename(String extension) {
        return UUID.randomUUID().toString().replace("-", "") +
                "_" + LocalDate.now().format(dateFormatter) +
                (extension != null ? extension : "");
    }

    private String getFileExtension(String filename) {
        return filename.contains(".") ? filename.substring(filename.lastIndexOf(".")) : "";
    }

    // ========== 内部类 ==========

    /**
     * 文件上传响应对象
     */
    public static final class FileUploadResponse {
        private final String folder;
        private final String serverFilename;
        private final String originalFilename;
        private final String contentType;
        private final long size;
        private final String storagePath;

        public FileUploadResponse(String folder, String serverFilename,
                                  String originalFilename, String contentType,
                                  long size, String storagePath) {
            this.folder = folder;
            this.serverFilename = serverFilename;
            this.originalFilename = originalFilename;
            this.contentType = contentType;
            this.size = size;
            this.storagePath = storagePath;
        }

        // Getter方法
        public String getFolder() { return folder; }
        public String getServerFilename() { return serverFilename; }
        public String getOriginalFilename() { return originalFilename; }
        public String getContentType() { return contentType; }
        public long getSize() { return size; }
        public String getStoragePath() { return storagePath; }

        @Override
        public String toString() {
            return "FileUploadResponse{" +
                    "folder='" + folder + '\'' +
                    ", serverFilename='" + serverFilename + '\'' +
                    ", originalFilename='" + originalFilename + '\'' +
                    ", contentType='" + contentType + '\'' +
                    ", size=" + size +
                    ", storagePath='" + storagePath + '\'' +
                    '}';
        }
    }
}